From 1c0859a723e350d2ea9b82f0343da6195722b566 Mon Sep 17 00:00:00 2001
From: Nikolay <nikkov@gmail.com>
Date: Mon, 4 Apr 2016 19:38:48 +0600
Subject: [PATCH 17/19] SPDIF experiments

---
 sound/soc/sunxi/spdif/sunxi_spdif.c | 92 +++++++++++++++----------------------
 sound/soc/sunxi/spdif/sunxi_spdma.c | 11 ++---
 2 files changed, 41 insertions(+), 62 deletions(-)

diff --git a/sound/soc/sunxi/spdif/sunxi_spdif.c b/sound/soc/sunxi/spdif/sunxi_spdif.c
index 5400e3f..9608b14 100644
--- a/sound/soc/sunxi/spdif/sunxi_spdif.c
+++ b/sound/soc/sunxi/spdif/sunxi_spdif.c
@@ -62,51 +62,39 @@ static struct clk *spdif_apbclk, *spdif_pll2clk, *spdif_pllx8, *spdif_moduleclk;
 void sunxi_snd_txctrl(struct snd_pcm_substream *substream, int on)
 {
 	u32 reg_val;
+	if (on) {
+		reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_FCTL);
+		reg_val |= SUNXI_SPDIF_FCTL_FTX;	//flush TX FIFO
+		reg_val |= SUNXI_SPDIF_FCTL_TXTL(0x10);	//TX FIFO empty Trigger Level
+		writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_FCTL);
 
-	reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCFG);
-	if (substream->runtime->channels == 1) {
-		reg_val |= SUNXI_SPDIF_TXCFG_SINGLEMOD;
-	}
-	else {
-		reg_val &= ~SUNXI_SPDIF_TXCFG_SINGLEMOD;
-	}
-	reg_val |= SUNXI_SPDIF_TXCFG_ASS;	//Sending the last audio (may be 0?)
-	reg_val |= SUNXI_SPDIF_TXCFG_CHSTMODE;	//Channel status A&B generated form TX_CHSTA
-	writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCFG);
-
-	/*flush TX FIFO and set FIFO empty trigger level*/
-	reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_FCTL);
-	reg_val |= SUNXI_SPDIF_FCTL_TXTL(0x10);	//TX FIFO empty Trigger Level
-	reg_val |= SUNXI_SPDIF_FCTL_FTX;	//flush TX FIFO
-	writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_FCTL);
-
-	/*clear interrupt status*/
-	reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_ISTA);
-	reg_val |= SUNXI_SPDIF_ISTA_TXCLR;
-	writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_ISTA);
+		reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_ISTA);
+		reg_val |= SUNXI_SPDIF_ISTA_TXCLR;	//clear interrupt status
+		writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_ISTA);
 
-	/*clear TX counter*/
-	writel(0, sunxi_spdif.regs + SUNXI_SPDIF_TXCNT);
+		writel(0, sunxi_spdif.regs + SUNXI_SPDIF_TXCNT);	//clear TX counter
 
-	if (on) {
-		//SPDIF TX ENABLE
 		reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCFG);
-		reg_val |= SUNXI_SPDIF_TXCFG_TXEN;
+		if (substream->runtime->channels == 1)
+			reg_val |= SUNXI_SPDIF_TXCFG_SINGLEMOD;
+		else
+			reg_val &= ~SUNXI_SPDIF_TXCFG_SINGLEMOD;
+		reg_val |= SUNXI_SPDIF_TXCFG_ASS;	//Sending the last audio (may be 0?)
+		reg_val |= SUNXI_SPDIF_TXCFG_CHSTMODE;	//Channel status A&B generated form TX_CHSTA
+		reg_val |= SUNXI_SPDIF_TXCFG_TXEN;	//SPDIF TX ENABLE
 		writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCFG);
 
-		//DRQ ENABLE
 		reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_INT);
-		reg_val |= SUNXI_SPDIF_INT_TXDRQEN;
+		reg_val |= SUNXI_SPDIF_INT_TXDRQEN;	//DRQ ENABLE
 		writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_INT);
+
 	} else {
-		//SPDIF TX DISABLE
 		reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCFG);
-		reg_val &= ~SUNXI_SPDIF_TXCFG_TXEN;
+		reg_val &= ~SUNXI_SPDIF_TXCFG_TXEN;	//SPDIF TX DISABLE
 		writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCFG);
 
-		//DRQ DISABLE
 		reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_INT);
-		reg_val &= ~SUNXI_SPDIF_INT_TXDRQEN;
+		reg_val &= ~SUNXI_SPDIF_INT_TXDRQEN;	//DRQ DISABLE
 		writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_INT);
 	}
 }
@@ -114,40 +102,33 @@ void sunxi_snd_txctrl(struct snd_pcm_substream *substream, int on)
 void sunxi_snd_rxctrl(struct snd_pcm_substream *substream, int on)
 {
 	u32 reg_val;
-
-	/*flush RX FIFO and set FIFO empty trigger level*/
-	reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_FCTL);
-	reg_val |= SUNXI_SPDIF_FCTL_RXTL(0x0F);	//RX FIFO Trigger Level
-	reg_val |= SUNXI_SPDIF_FCTL_FRX;	//flush RX FIFO	
-	writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_FCTL);
-	
-	/*clear interrupt status*/
-	reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_ISTA);
-	reg_val |= SUNXI_SPDIF_ISTA_RXCLR;
-	writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_ISTA);
 	
-	/*clear RX counter*/
-	writel(0, sunxi_spdif.regs + SUNXI_SPDIF_RXCNT);
-
 	if (on) {
-		/*SPDIF RX ENABLE*/
+		reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_FCTL);
+		reg_val |= SUNXI_SPDIF_FCTL_RXTL(0x0F);	//RX FIFO Trigger Level
+		reg_val |= SUNXI_SPDIF_FCTL_FRX;	//flush RX FIFO	
+		writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_FCTL);
+
+		reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_ISTA);
+		reg_val |= SUNXI_SPDIF_ISTA_RXCLR;	//clear interrupt status
+		writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_ISTA);
+
+		writel(0, sunxi_spdif.regs + SUNXI_SPDIF_RXCNT);	//clear RX counter
+
 		reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_RXCFG);
-		reg_val |= SUNXI_SPDIF_RXCFG_RXEN;	
+		reg_val |= SUNXI_SPDIF_RXCFG_RXEN;	//SPDIF RX ENABLE
 		writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_RXCFG);
 		
-		/*DRQ ENABLE*/
 		reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_INT);
-		reg_val |= SUNXI_SPDIF_INT_RXDRQEN;	
+		reg_val |= SUNXI_SPDIF_INT_RXDRQEN;	//DRQ ENABLE
 		writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_INT);
 	} else {
-		/*SPDIF TX DISABLE*/
 		reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_RXCFG);
-		reg_val &= ~SUNXI_SPDIF_RXCFG_RXEN;	
+		reg_val &= ~SUNXI_SPDIF_RXCFG_RXEN;	//SPDIF RX DISABLE
 		writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_RXCFG);
 		
-		/*DRQ DISABLE*/
 		reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_INT);
-		reg_val &= ~SUNXI_SPDIF_INT_RXDRQEN;	
+		reg_val &= ~SUNXI_SPDIF_INT_RXDRQEN;	//DRQ DISABLE
 		writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_INT);
 	}
 }
@@ -286,8 +267,7 @@ static int sunxi_spdif_trigger(struct snd_pcm_substream *substream,
 {
 	int ret = 0;
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct sunxi_dma_params *dma_data =
-					snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+	struct sunxi_dma_params *dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
 	switch (cmd) {
 		case SNDRV_PCM_TRIGGER_START:
diff --git a/sound/soc/sunxi/spdif/sunxi_spdma.c b/sound/soc/sunxi/spdif/sunxi_spdma.c
index d5377fc..b2af6a9 100644
--- a/sound/soc/sunxi/spdif/sunxi_spdma.c
+++ b/sound/soc/sunxi/spdif/sunxi_spdma.c
@@ -45,7 +45,7 @@ static const struct snd_pcm_hardware sunxi_pcm_out_hardware = {
 	.channels_min		= 1,
 	.channels_max		= 2,
 	.buffer_bytes_max	= 128*1024,  /* value must be (2^n)Kbyte size */
-	.period_bytes_min	= 1024,//1024*4,
+	.period_bytes_min	= 1024*4,
 	.period_bytes_max	= 1024*32,//1024*128,
 	.periods_min		= 4,
 	.periods_max		= 8,
@@ -63,7 +63,7 @@ static const struct snd_pcm_hardware sunxi_pcm_in_hardware = {
 	.channels_min		= 1,
 	.channels_max		= 2,
 	.buffer_bytes_max	= 128*1024,  /* value must be (2^n)Kbyte size */
-	.period_bytes_min	= 1024,//1024*4,
+	.period_bytes_min	= 1024*4,
 	.period_bytes_max	= 1024*32,//1024*128,
 	.periods_min		= 4,
 	.periods_max		= 8,
@@ -88,12 +88,11 @@ static void sunxi_pcm_enqueue(struct snd_pcm_substream *substream)
 {
 	struct sunxi_runtime_data *prtd = substream->runtime->private_data;
 	dma_addr_t pos = prtd->dma_pos;
-	unsigned int limit;
 	int ret;
+	unsigned int limit = prtd->dma_limit;
 	unsigned long len = prtd->dma_period;
 	int read = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 0 : 1;
 
-  	limit = prtd->dma_limit;
   	while(prtd->dma_loaded < limit){
 		if((pos + len) > prtd->dma_end){
 			len  = prtd->dma_end - pos;
@@ -296,15 +295,20 @@ static int sunxi_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		sunxi_dma_start(prtd->params);
 		prtd->state |= ST_RUNNING;
+		/* enqueue dma buffers */
+		sunxi_pcm_enqueue(substream);
+		sunxi_dma_start(prtd->params);
+		ret =0;
 		break;
 
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		sunxi_dma_stop(prtd->params);
 		prtd->state &= ~ST_RUNNING;
+		sunxi_dma_stop(prtd->params);
+		prtd->dma_loaded = 0;
+		ret = 0;
 		break;
 
 	default:
-- 
1.9.1

